package com.quanyue.music.file.service.impl;

import com.quanyue.auto.cache.CacheService;
import com.quanyue.auto.fs.StoreService;
import com.quanyue.auto.util.AssertUtils;
import com.quanyue.auto.util.StringUtils;
import com.quanyue.music.domain.constant.CacheConstants;
import com.quanyue.music.domain.constant.FMStatus;
import com.quanyue.music.domain.constant.FMType;
import com.quanyue.music.domain.constant.JobEvent;
import com.quanyue.music.domain.entity.*;
import com.quanyue.music.file.mapper.*;
import com.quanyue.music.file.service.FMFileService;
import com.quanyue.music.file.type.*;
import com.shzisg.mybatis.mapper.page.Page;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.beans.Transient;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class FMFileServiceImpl implements FMFileService {
    private final String path = "/opt/music/admin/server/static/dist/excel/";
    @Autowired
    private FMFileMapper fmFileMapper;
    @Autowired
    private FMNamesMapper fmNamesMapper;
    @Autowired
    private StoreService storeService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private JobRecordMapper jobRecordMapper;
    @Autowired
    private LikeUserMapper likeUserMapper;
    @Autowired
    private LikeDetailMapper likeDetailMapper;
    private JobRecord jobRecord;
    private LocalDateTime lastTime;
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    @Transactional
    public void upload(FMUpload fmUpload) {
        Fm fm = fmUpload.getFm();
        if (fm.getType().equals(FMType.SOS)) {
            Fm checkFm = fmFileMapper.findByType(fm.getType());
            if (checkFm != null) fmFileMapper.deleteOne(checkFm.getId());
            fm.setStatus(FMStatus.FINALIZED);
        } else {
            fm.setStatus(FMStatus.NOT_FINALIZED);
        }
        fm.setDelFlag(false);
        fm.setCreateTime(LocalDateTime.now());
        fm.setModifyTime(LocalDateTime.now());
        fm.setImage(storeService.toFile(fm.getImage()));
        if (StringUtils.isBlank(fm.getTag())) fm.setTag("NONE");
        if (StringUtils.isBlank(fm.getSingerName())) fm.setSingerName("NONE");
        fmFileMapper.insert(fm);
        log.info("upload标题名: {}", fm.getTitle() + "file文件:" + fm.getFmFile());

        List <FmNames> fmNames = fmUpload.getNames();
        fmNames.forEach(names -> {
            names.setFmId(fm.getId());
            names.setCreateTime(LocalDateTime.now());
            fmNamesMapper.insert(names);
        });
    }

    @Override
    public FMUpload findSOS() {
        Fm fm = fmFileMapper.findByType(FMType.SOS);
        if (fm == null) return new FMUpload();
        fm.setImage(storeService.toPublic(fm.getImage()));
        List <FmNames> names = fmNamesMapper.findByFmId(fm.getId());
        FMUpload result = new FMUpload();
        result.setFm(fm);
        result.setNames(names);
        return result;
    }

    @Override
    @Transient
    public void update(FMUpload fmUpload) {
        Fm fm = fmUpload.getFm();
        Fm checkFm = fmFileMapper.findOne(fm.getId());
        AssertUtils.notNull(checkFm, "没有该文件");
        fm.setCreateTime(checkFm.getCreateTime());
        fm.setModifyTime(LocalDateTime.now());
        fm.setImage(storeService.toFile(fm.getImage()));
        fm.setFmFile(fm.getFmFile());
        fm.setDelFlag(false);
        fmFileMapper.updateSelective(fm);
        fmNamesMapper.deleteByFmId(fm.getId());
        List <FmNames> fmNames = fmUpload.getNames();
        fmNames.forEach(names -> {
            names.setId(null);
            names.setFmId(fm.getId());
            names.setCreateTime(LocalDateTime.now());
            fmNamesMapper.insert(names);
        });
    }

    @Override
    public void delete(String id) {
        Fm fm = new Fm();
        fm.setId(id);
        fm.setDelFlag(true);
        fm.setModifyTime(LocalDateTime.now());
        fmFileMapper.updateSelective(fm);
    }

    @Override
    @Transactional
    public boolean updateLikeCount(FMLikeRequest request, String userId) {
        int i = 1;
        if (request.getCancel()) {
            i = -1;
        }
        LikeDetail likeDetail = likeDetailMapper.findByZoneAndFM(request.getFmId(), request.getZoneType());
        if (likeDetail != null) {
            likeDetail.setCount(likeDetail.getCount() + i);
            likeDetailMapper.update(likeDetail);
        } else {
            LikeDetail newLikeDetail = new LikeDetail();
            newLikeDetail.setFmId(request.getFmId());
            newLikeDetail.setZone(request.getZoneType());
            newLikeDetail.setCreateTime(LocalDate.now());
            newLikeDetail.setCount(1);
            likeDetailMapper.insert(newLikeDetail);
        }

        UserLike userLike = likeUserMapper.findByFmId(request.getFmId(), userId);
        if (userLike != null) {
            userLike.setDelFlag(request.getCancel());
            likeUserMapper.update(userLike);
            return true;
        }
        UserLike record = new UserLike();
        record.setFmId(request.getFmId());
        record.setUserId(userId);
        record.setCreateTime(LocalDateTime.now());
        record.setDelFlag(false);
        likeUserMapper.insert(record);
        return true;
    }

    @Override
    public void updateLikeCount(List <Fm> fmList) {
        fmFileMapper.updateSelectiveAll(fmList);
    }

    @Override
    public Page <FMDetailList> findList(FMDetailRequest request) {
        Page <FMDetailList> fmDetailPage = fmFileMapper.findList(request);
        fmDetailPage.getContent().forEach(fm -> {
            fm.setImage(storeService.toPublic(fm.getImage()));
            fm.setNames(fmNamesMapper.findByFmId(fm.getId()));
        });
        return fmDetailPage;
    }

    @Override
    public String findListExcel(FMListExcel request) {
        List <FMDetailList> fmDetails = fmFileMapper.findExcelList(request);
        fmDetails.forEach(fm -> {
            fm.setImage(storeService.toPublic(fm.getImage()));
            fm.setNames(fmNamesMapper.findByFmId(fm.getId()));
        });
        return createExcel(fmDetails);
    }

    private String createExcel(List <FMDetailList> fmDetails) {
        try {
            String fileName = "FM_LIST.xls";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            //  打开文件
            WritableWorkbook book = Workbook.createWorkbook(new File(path, fileName));
            //  生成名为“第一页”的工作表，参数0表示这是第一页
            WritableSheet sheet = book.createSheet(" 第一页 ", 0);

            //  将定义好的单元格添加到工作表中  在Label对象的构造子中指名单元格位置是第一列第一行(0,0)
            sheet.addCell(new Label(0, 0, "ID"));
            sheet.addCell(new Label(1, 0, "标题"));
            sheet.addCell(new Label(2, 0, "MC"));
            sheet.addCell(new Label(3, 0, "简介"));
            sheet.addCell(new Label(4, 0, "Status"));
            sheet.addCell(new Label(5, 0, "Tag"));
            sheet.addCell(new Label(6, 0, "歌曲1"));
            sheet.addCell(new Label(7, 0, "歌曲2"));
            sheet.addCell(new Label(8, 0, "歌曲3"));
            sheet.addCell(new Label(9, 0, "歌曲4"));
            sheet.addCell(new Label(10, 0, "歌曲5"));
            sheet.addCell(new Label(11, 0, "歌曲6"));
            sheet.addCell(new Label(12, 0, "歌曲7"));
            sheet.addCell(new Label(13, 0, "歌曲8"));
            sheet.addCell(new Label(14, 0, "歌曲9"));

            int row = 1;
            for (FMDetailList result : fmDetails) {
                int column = 0;
                sheet.addCell(new Label(column++, row, result.getKeyId()));
                sheet.addCell(new Label(column++, row, result.getTitle()));
                sheet.addCell(new Label(column++, row, result.getSingerName()));
                sheet.addCell(new Label(column++, row, result.getDescription()));
                sheet.addCell(new Label(column++, row, result.getStatus().name()));
                sheet.addCell(new Label(column++, row, result.getTagName()));
                for (int i = 0; i < result.getNames().size(); i++) {
                    if (i > 8) break;
                    sheet.addCell(new Label(column++, row, result.getNames().get(i).getFmName()));
                }
                ++row;
            }
            //  写入数据并关闭文件
            book.write();
            book.close();
            return "/excel/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @PostConstruct
    private void init() {
        jobRecord = jobRecordMapper.findByEvent(JobEvent.FM_LIKE_SUMMARY);
        lastTime = jobRecord.getBeginTime();
        cacheService.put(CacheConstants.LIKE_LOG.name(), new ArrayList <>());
    }
}
